#include "GetFileList.h"

#pragma warning(disable:4996)

#ifdef WIN32
#include <windows.h>
#endif

namespace GET_FILE_LIST
{


#define MAXNAME 512

class FileFind
{
public:
  FileFind::FileFind(const char *dirname,const char *spec)
  {
    if ( dirname && strlen(dirname) )
      sprintf_s(mSearchName,MAXNAME,"%s\\%s",dirname,spec);
    else
      sprintf_s(mSearchName,MAXNAME,"%s",spec);
   }

  FileFind::~FileFind(void)
  {
  }


  bool FindFirst(char *name,bool &isDirectory)
  {
    bool ret=false;

    #ifdef WIN32
    hFindNext = FindFirstFileA(mSearchName, &finddata);
    if ( hFindNext == INVALID_HANDLE_VALUE )
      ret =  false;
     else
     {
       bFound = 1; // have an initial file to check.
	   strncpy(name,finddata.cFileName,MAXNAME);
       ret =  true;
     }
     #endif
     #ifdef LINUX_GENERIC
     mDir = opendir(".");
     ret = FindNext(name,isDirectory);
    #endif
    return ret;
  }

  bool FindNext(char *name,bool &isDirectory)
  {
    bool ret = false;

    #ifdef WIN32
    while ( bFound )
    {
      bFound = FindNextFileA(hFindNext, &finddata);
      if ( bFound && (finddata.cFileName[0] != '.') )
      {
		  if ( (finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
		  {
			  isDirectory = true;
		  }
		  else
		  {
			  isDirectory = false;
		  }
        strncpy(name,finddata.cFileName,MAXNAME);
        ret = true;
        break;
      }
    }
    if ( !ret )
    {
      bFound = 0;
      FindClose(hFindNext);
    }
    #endif

    #ifdef LINUX_GENERIC

    if ( mDir )
    {
      while ( 1 )
      {

        struct direct *di = readdir( mDir );

        if ( !di )
        {
          closedir( mDir );
          mDir = 0;
          ret = false;
          break;
        }

        if ( strcmp(di->d_name,".") == 0 || strcmp(di->d_name,"..") == 0 )
        {
          // skip it!
        }
        else
        {
          strncpy(name,di->d_name,MAXNAME);
          ret = true;
          break;
        }
      }
    }
    #endif
    return ret;
  }

private:
  char mSearchName[MAXNAME];
#ifdef WIN32
  WIN32_FIND_DATAA finddata;
  HANDLE hFindNext;
  int bFound;
#endif
#ifdef LINUX_GENERIC
  DIR      *mDir;
#endif
};

unsigned int getFileList(const char *startingDirectory,const char *fileSpec,bool recursive,FileListVector &fileList)
{
	FileListVector subDirectories;
	FileFind ff(startingDirectory,fileSpec);
	char name[MAXNAME];
	bool isDirectory;
	bool found = ff.FindFirst(name,isDirectory);
	if ( found )
	{
		while ( found )
		{
			if( strcmp(name,".") != 0 )
			{
				if ( isDirectory )
				{
					if ( recursive )
					{
						char scratch[MAXNAME];
						sprintf_s(scratch,MAXNAME,"%s/%s", startingDirectory, name );
						std::string subDir = scratch;
						subDirectories.push_back(subDir);
					}
				}
				else
				{
					char scratch[MAXNAME];
					sprintf_s(scratch,MAXNAME,"%s/%s", startingDirectory, name );
					std::string fname = scratch;
					fileList.push_back(fname);
				}
			}
			found = ff.FindNext(name,isDirectory);
		}
	}
	for (FileListVector::iterator i=subDirectories.begin(); i!=subDirectories.end(); ++i)
	{
		getFileList( (*i).c_str(), fileSpec, recursive, fileList );
	}
	return (unsigned int)fileList.size();
}


}; // end of namespace
